package com.cdtye.itps.cms.service.datasysn;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cdtye.common.kafkacore.model.attr.ConsumerErrorAttr;
import com.cdtye.common.kafkacore.model.entity.KfkConsumerRule;
import com.cdtye.common.kafkacore.model.enums.KfkErrorFieldTypeEnum;
import com.cdtye.common.kafkacore.model.enums.KfkErrorTypeEnum;
import com.cdtye.common.kafkacore.service.KfkConsumerRuleService;
import com.cdtye.common.webcore.constants.WebConstants;
import com.cdtye.common.webcore.enums.YesNoEnum;
import com.cdtye.common.webcore.util.MonitorLogUtil;
import com.cdtye.common.webcore.util.ObjectUtil;
import com.cdtye.itps.cms.dao.lineSite.entity.JcLineSite;
import com.cdtye.itps.dubbos.basic.BasicService;
import com.cdtye.itps.models.base.model.attr.basic.*;
import com.cdtye.itps.models.base.model.entity.basic.Pillar;
import com.cdtye.itps.models.base.model.entity.monitor.NewPretreatmentLog;
import com.cdtye.itps.models.base.model.vo.basic.PillarVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * 预处理公共验证处理方法封装
 *
 * @author LuCong
 * @date 2020/7/20
 */
@Service
@Slf4j
public class PreHandleService {

    private static final String LINE_END_X = "线";
    private static final String SITE_END_Z = "站";
    private static final String PILLAR_PT = "普铁";
    private static final String PILLAR_GT = "高铁";
    private static final String PILLAR_ZZ = "支柱";

    @DubboReference
    private BasicService basicService;
    @Autowired
    private KfkConsumerRuleService kfkConsumerRuleService;

    @Value("${cdtye.log.path}")
    private String path;

    /**
     * 保存监控日志信息
     *
     * @param interfaceStr
     * @param consumerNum
     * @param successNum
     * @throws Exception
     */
    public void saveMonitorLog(String interfaceStr, Integer consumerNum, Integer successNum) throws Exception {
        NewPretreatmentLog log = new NewPretreatmentLog(interfaceStr,
                MonitorLogUtil.getAddress(),
                successNum,
                consumerNum - successNum,
                1,
                ""
        );
        MonitorLogUtil.writeLog(path, JSONObject.toJSONString(log));
    }

    /**
     * 匹配并获取区站，未匹配成功不抛异常
     *
     * @param allSiteMap
     * @param siteAttr
     * @param lineAttr
     * @return
     */
    public SiteAttr getSite2(Map<String, JcLineSite> allSiteMap, SiteAttr siteAttr, LineAttr lineAttr) {
        Object preObj = checkSite2(allSiteMap, siteAttr, lineAttr);
        if (preObj instanceof ConsumerErrorAttr) {
            return null;
        } else {
            return (SiteAttr) preObj;
        }
    }


    /**
     * 匹配区站
     * @param allSiteMap
     * @param siteAttr
     * @param lineAttr
     * @return 返回若是ConsumerErrorAttr对象时，表示预处理异常。
     * 这几个值需要根据业务判断是否修改。
     */
    public Object checkSite2(Map<String, JcLineSite> allSiteMap, SiteAttr siteAttr, LineAttr lineAttr) {
        if (siteAttr == null) {
            return new SiteAttr();
        }
        String siteCode = siteAttr.getLineSiteCode(), siteName = siteAttr.getSiteName();
        if (StringUtils.isBlank(siteCode) && StringUtils.isBlank(siteName)) {
            return new SiteAttr();
        }
        //1、根据code获取数据
        JcLineSite entity = allSiteMap.get(siteCode);
        //2、根据name获取数据
        String lineId = lineAttr == null && StringUtils.isBlank(lineAttr.getLineId()) ? "" : lineAttr.getLineId();
        if (entity == null && StringUtils.isNotBlank(siteName)) {
            entity = allSiteMap.get(lineId + siteName);
            //3、匹配去掉"站"
            if (entity == null) {
                entity = allSiteMap.get(lineId + siteName.replaceAll(SITE_END_Z, ""));
            }
            //4、匹配站场交换
            if (entity == null && siteName.contains(WebConstants.CHAR_HX)) {
                String[] siteArr = siteName.split(WebConstants.CHAR_HX);
                String tempSiteName = siteArr[1] + WebConstants.CHAR_HX + siteArr[0];
                entity = allSiteMap.get(lineId + tempSiteName);
                //匹配交换并去掉"站"
                if (entity == null) {
                    entity = allSiteMap.get(lineId + tempSiteName.replaceAll(SITE_END_Z, ""));
                }
            }
        }
        //4、按规则预处理
        String errorType = KfkErrorTypeEnum.LINE_SITE.getType();
        //线路名称_区站名称
        String lineName = lineAttr == null || StringUtils.isBlank(lineAttr.getLineName()) ? "" : lineAttr.getLineName();
        String errorCode = StringUtils.isBlank(siteName) ? "" : new StringBuilder(lineName).append("_").append(siteName).toString();
        if (entity == null) {
            //防止预处理无错误code
            if (StringUtils.isBlank(siteCode)) {
                siteCode = errorCode;
            }
            return getSiteErrorAttr(siteCode, "区站不存在");
        }else{
            SiteAttr siteAttr1 = new  SiteAttr();
            siteAttr1.setSiteId(entity.getSiteId());
            siteAttr1.setLineId(entity.getSeclineId());
            siteAttr1.setLineSiteCode(entity.getMCode());
            siteAttr1.setSiteName(entity.getSiteName());
            return siteAttr1;
        }
    }

    /**
     * 获取区站错误默认属性
     *
     * @param errorCode
     * @param errorReason
     * @return
     */
    public ConsumerErrorAttr getSiteErrorAttr(String errorCode, String errorReason) {
        return new ConsumerErrorAttr().setErrorType(KfkErrorTypeEnum.LINE_SITE.getType()).setErrorCode(errorCode).setErrorReason(errorReason)
                .setErrorField("siteAttr").setErrorFieldType(KfkErrorFieldTypeEnum.OBJECT.getType())
                .setErrorClazzName(SiteAttr.class.getName()).setStatus(YesNoEnum.NO.getCode());
    }

    /**
     * 匹配支柱，未成功不抛异常
     *
     * @param pillarAttr
     * @param lineAttr
     * @param siteAttr
     * @param directionAttr
     * @param tunnelAttr
     * @param roadMark
     * @return
     */
    public Pillar getPillar(PillarAttr pillarAttr, LineAttr lineAttr, SiteAttr siteAttr, DirectionAttr directionAttr
            , TunnelAttr tunnelAttr, Double roadMark, String dataSysnKey) {
        Object preObj = checkPillar(pillarAttr, lineAttr, siteAttr, directionAttr, tunnelAttr, roadMark, dataSysnKey);
        if (preObj instanceof ConsumerErrorAttr) {
            return new Pillar();
        } else {
            return (Pillar) preObj;
        }
    }


    /**
     * 验证支柱编码是否存在,并且获取支柱所有信息
     * 优先按支柱编码进行匹配，
     *
     * @param pillarAttr
     * @param lineAttr
     * @param siteAttr
     * @param directionAttr
     * @param tunnelAttr
     * @param roadMark
     * @return 返回若是ConsumerErrorAttr对象时，表示预处理异常。
     * 预处理异常对象会设置默认的字段名为errorField=xxAttr,errorFieldType=Object,errorClazz=对象.class
     * 这几个值需要根据业务判断是否修改。
     */
    public Object checkPillar(PillarAttr pillarAttr, LineAttr lineAttr, SiteAttr siteAttr, DirectionAttr directionAttr
            , TunnelAttr tunnelAttr, Double roadMark, String  dataSysnKey) {
        String pillarCode = pillarAttr == null ? "" : pillarAttr.getPillarCode(), pillarNum = pillarAttr == null ? "" : pillarAttr.getPillarNum();
        if (StringUtils.isBlank(pillarCode) && StringUtils.isBlank(pillarNum) && roadMark == null) {
            return new Pillar();
        }
        Pillar entity = null;
        //1、根据code获取数据
        if (StringUtils.isNotBlank(pillarCode)) {
            entity = basicService.findPillarByCode(pillarCode);
        }
        //2、按支柱号进行匹配，线路+区站不能为空
        String lineId = lineAttr == null || StringUtils.isBlank(lineAttr.getLineId()) ? "" : lineAttr.getLineId();
        String siteId = siteAttr == null || StringUtils.isBlank(siteAttr.getSiteId()) ? "" : siteAttr.getSiteId();
        String directionId = directionAttr == null || StringUtils.isBlank(directionAttr.getDirectionId()) ? "" : directionAttr.getDirectionId();
        String tunnelId = tunnelAttr == null || StringUtils.isBlank(tunnelAttr.getTunnelId()) ? "" : tunnelAttr.getTunnelId();
        if (entity == null && StringUtils.isNotBlank(pillarNum) && StringUtils.isNotBlank(lineId) && StringUtils.isNotBlank(siteId)) {
            PillarVo pillarVo = new PillarVo().setLineId(lineId).setDirectionId(directionId).setSiteId(siteId)
                    .setPillarNum(pillarNum).setTunnelId(tunnelId);
            entity = basicService.findPillarByBase(pillarVo);
            //不是隧道  用0补全4位 匹配
            if (entity == null && ObjectUtil.isNumeric(pillarNum) && pillarNum.length() < 4) {
                pillarVo.setPillarNum(StringUtils.leftPad(pillarNum, 4, "0"));
                entity = basicService.findPillarByBase(pillarVo);
            }
            if (entity == null) {
                //对支柱号进行特殊匹配处理在查询
                String nowPillarNum = pillarNum;
                //如果支柱匹配不上需要考虑如下几种情况
                if (pillarNum.contains(WebConstants.CHAR_JH) || pillarNum.contains(PILLAR_PT) || pillarNum.contains(PILLAR_GT) || pillarNum.contains(PILLAR_ZZ)) {
                    //1，以#、普铁、高铁、支柱结尾的支柱号直接去掉
                    nowPillarNum = pillarNum.replace(WebConstants.CHAR_JH, "").replace(PILLAR_PT, "")
                            .replace(PILLAR_GT, "").replace(PILLAR_ZZ, "");
                    pillarVo.setPillarNum(nowPillarNum);
                    entity = basicService.findPillarByBase(pillarVo);
                }
                //不是隧道  用0补全4位 匹配
                if (entity == null && ObjectUtil.isNumeric(nowPillarNum) && nowPillarNum.length() < 4) {
                    pillarVo.setPillarNum(StringUtils.leftPad(nowPillarNum, 4, "0"));
                    entity = basicService.findPillarByBase(pillarVo);
                }
            }
        }
        //3、按规则预处理
        String errorType = KfkErrorTypeEnum.PILLAR.getType();
        //预处理规则自定义,线路名称_行别名称_区站名称_隧道名称_支柱号
        String lineName = lineAttr == null || StringUtils.isBlank(lineAttr.getLineName()) ? "" : lineAttr.getLineName();
        String directionName = directionAttr == null || StringUtils.isBlank(directionAttr.getDirectionName()) ? "" : "_" + directionAttr.getDirectionName();
        String siteName = siteAttr == null || StringUtils.isBlank(siteAttr.getSiteName()) ? "" : "_" + siteAttr.getSiteName();
        String tunnelName = tunnelAttr == null || StringUtils.isBlank(tunnelAttr.getTunnelName()) ? "" : "_" + tunnelAttr.getTunnelName();
        String errorCode = StringUtils.isBlank(pillarNum) ? "" : new StringBuilder(lineName)
                .append(directionName).append(siteName).append(tunnelName)
                .append("_").append(pillarNum).toString();
        if (entity == null) {
            List<KfkConsumerRule> ruleList = kfkConsumerRuleService.findByErrorType(errorType, dataSysnKey);
            for (KfkConsumerRule o : ruleList) {
                //防止没有该字段报错
                if (o.getType() == null) {
                    continue;
                }
                if (o.getType() == 0) {
                    //编码预处理,按编码或名称
                    String key = o.getErrorType() + o.getErrorCode();
                    //按异常编码进行匹配校正
                    boolean codeFlag = StringUtils.isNotBlank(pillarCode) && key.equals(errorType + pillarCode);
                    boolean nameFlag = StringUtils.isNotBlank(errorCode) && key.equals(errorType + errorCode);
                    if (codeFlag || nameFlag) {
                        entity = basicService.findPillarByCode(JSON.parseObject(JSON.toJSONString(o.getData()), PillarAttr.class).getPillarCode());
                        break;
                    }
                } else if (o.getType() == 2 && StringUtils.isNotBlank(pillarNum) && StringUtils.isNotBlank(lineId) && StringUtils.isNotBlank(siteId)) {
                    //替换规则操作,别名暂时不做任何处理
                    String newName = "";
                    for (String rule : o.getRuleList()) {
                        if (pillarNum.endsWith(rule)) {
                            newName = pillarNum.substring(0, pillarNum.lastIndexOf(rule)) + ObjectUtil.covToString(o.getData()).replaceAll("\\s*", "");
                            break;
                        }
                    }
                    if (StringUtils.isNotBlank(newName)) {
                        //按替换后的支柱号查询
                        PillarVo pillarVo = new PillarVo().setLineId(lineId).setDirectionId(directionId).setSiteId(siteId)
                                .setPillarNum(newName).setTunnelId(tunnelId);
                        entity = basicService.findPillarByBase(pillarVo);
                        break;
                    }
                }
            }
        }
        //4、最后按公里标匹配
        if (entity == null && StringUtils.isNotBlank(lineId) && roadMark != null) {
            entity = basicService.findPillarByRoadMark(lineId, directionId, roadMark);
            //公里标未匹配成功直接返回空支柱
            if (entity == null) {
//                return new Pillar();
                return getPillarErrorAttr(pillarCode, "公里标不存在");
            }
        }
        if (entity == null) {
            //防止预处理无错误code
            if (StringUtils.isBlank(pillarCode)) {
                pillarCode = errorCode;
            }
            return getPillarErrorAttr(pillarCode, "支柱不存在");
        }
        return entity;
    }

    /**
     * 获取支柱错误默认属性
     *
     * @param errorCode
     * @param errorReason
     * @return
     */
    public ConsumerErrorAttr getPillarErrorAttr(String errorCode, String errorReason) {
        return new ConsumerErrorAttr().setErrorType(KfkErrorTypeEnum.PILLAR.getType()).setErrorCode(errorCode).setErrorReason(errorReason)
                .setErrorField("pillarAttr").setErrorFieldType(KfkErrorFieldTypeEnum.OBJECT.getType())
                .setErrorClazzName(PillarAttr.class.getName()).setStatus(YesNoEnum.NO.getCode());
    }
}
